package com.fg.pro.admin.filter;

import cn.hutool.core.util.StrUtil;
import com.fg.pro.admin.config.LoginByFree;
import com.fg.pro.admin.config.LoginPassTokenByFree;
import com.fg.pro.model.sys.dto.SysUserDto;
import com.fg.pro.model.feign.SysFeignClient;
import com.fg.pro.model.utils.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import static org.springframework.http.HttpStatus.UNAUTHORIZED;

@Component
@Slf4j
public class AdminFilter implements Ordered, GlobalFilter {

    @Autowired
    LoginByFree loginByFree;

    @Autowired
    LoginPassTokenByFree loginPassTokenByFree;

    @Autowired
    @Lazy
    SysFeignClient sysFeignClient;

    private final static AntPathMatcher PATH_MATCHER = new AntPathMatcher();

//    @Autowired
//    RabbitTemplate rabbitTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取request和response对象
        ServerHttpRequest request = exchange.getRequest();
        Flux<DataBuffer> body = request.getBody();
        ServerHttpResponse response = exchange.getResponse();

        // 2.判断是否需要登录，不需要则放行
        String[] loginByFreePathurl = loginByFree.getPathurl();
        boolean check = checkUriByArray(loginByFreePathurl, request.getURI().getPath());
        if (check) {
            return chain.filter(exchange);
        }

        // 3.获取token
        String token = request.getHeaders().getFirst("fuge_token");

        // 4.判断token是否存在
        if (StrUtil.isBlank(token)) {
            response.setStatusCode(UNAUTHORIZED);
            return response.setComplete();
        }

        try {
            // 5.判断token是否有效
            Claims claimsBody = AppJwtUtil.getClaimsBody(token);
            //是否是过期
            int result = AppJwtUtil.verifyToken(claimsBody);
            if (result == 1 || result == 2) {
                response.setStatusCode(UNAUTHORIZED);
                return response.setComplete();
            }
            // 6.用户状态和登入权限校验
            Long id = Long.valueOf(claimsBody.get("adminId").toString());
            // 6.1开启一个线程，返回用户信息
            FutureTask<SysUserDto> task = new FutureTask<>(new Callable<SysUserDto>() {
                @Override
                public SysUserDto call() throws Exception {
                    SysUserDto sysUserDto = sysFeignClient.feignGetById(id.toString());
                    return sysUserDto;
                }
            });
            new Thread(task, "getUserAdminDtoThread").start();
            SysUserDto userDto = task.get();
            // 6.2 对比用户信息
            if (userDto.getUserState().equals(0)) {
                response.setStatusCode(UNAUTHORIZED);
                return response.setComplete();
            }
            // 6.3 将userId保存到请求头中返回给微服务
//            request = request.mutate().headers(httpHeaders -> {
//                httpHeaders.add("userId", id.toString());
//            }).build();
//            request.getHeaders().add("userId",id.toString());
            request = request.mutate()
                    .header("userId", id.toString())
                    .build();


            // 7.身份请求路径校验
            List<String> loginPassTokenList = Arrays.asList(loginPassTokenByFree.pathurl);
            userDto.getMenuStrList().addAll(loginPassTokenList);
            boolean authFlag = checkUriByList(userDto.getMenuStrList(), request.getURI().getPath());
            if (!authFlag) {
                response.setStatusCode(UNAUTHORIZED);
                return response.setComplete();
            }
            // 8.发送日志记录
//            rabbitTemplate.convertAndSend(MQ_LOG_EXCHANGE,MQ_LOG_BINDING_KEY, JSONUtil.toJsonStr(new SysLogDtos(request.getURI().getPath(),id,null)));
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatusCode(UNAUTHORIZED);
            return response.setComplete();
        }
        // 8.确定无误后放行
//        return chain.filter(exchange);
        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return 0;
    }

    public boolean checkUriByArray(String[] urlArr, String requestURI) {
        for (String url : urlArr) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) {
                return true;
            }
        }
        return false;
    }

    public boolean checkUriByList(List<String> list, String requestURI) {
        for (String mapperStr : list) {
            if (StrUtil.isNotBlank(mapperStr)) {
                boolean match = PATH_MATCHER.match(mapperStr, requestURI);
                if (match) {
                    return true;
                }
            }

        }
        return false;
    }

}
